package pixel;

/*
 * Bild-"Erzeugung" in dem Puffer eines BufferedImage
 *   durch direkte "Bit-Schiebe-Operationen"
 *   zusaetzlich koennen die Graphics-Befehle verwendet werden
 * Speicherung des Bildes:
 *   - durch Auslesen des Puffers und Schreiben einer (Text-) Datei
 *     im PPM-Format (dies koennen gaengige Programme lesen)
 *   - durch direkte Abspeicherung des BufferedImage (mit ImageIO)
 *     im PNG-Format (JPEG geht auch; dabei treten aber immer (?)
 *     Farbverfaelschungen auf)
 *     (um diese zu vermeiden muss ein ImageWriter erzeugt werden
 *      und eine Kompression eingestellt werden)
 *     (Kompression von PNG-Bildern einzustellen, scheint aber immer noch
 *      nicht zu gehen (es gibt plugin in com.sun. ...) -- das
 *      ist aber nicht �berall vorhanden.)
 *     IrfanView schafft es, die Dateigroesse auf 497 Bytes zu druecken,
 *     vergl. BildApp00AImageIO.java, wo ein so komprimiertes Bild
 *     gelesen wird.
 */

import java.io.*; // wg speichern
import javax.swing.*;
import java.awt.*; // Graphics
import java.awt.event.*;
import java.awt.image.*; // BufferedImage
import javax.imageio.ImageIO;


public class MakePPM extends JFrame{
  // Exemplar-Konstante:

  // Exemplar-Variablen:

  // Komponenten deklarieren:
  private JButton btnStart;
  private JButton btnSchreibenPPM;
  private JButton btnSchreibenPNG;
  private JLabel lblSchreibName;
  private JTextField tfSchreibName;
  private MeinPanel pZentral;

  // Komponenten erzeugen:
  private void erzeugeKomponenten(){
    btnStart=new JButton("los geht's!");
    btnSchreibenPPM=new JButton("speichern (PPM ASCII)");
    btnSchreibenPNG=new JButton("speichern (PNG)");
    lblSchreibName=new JLabel("SchreibName (ohne Endung)");
    tfSchreibName=new JTextField("BILD", 10);
    pZentral=new MeinPanel();
  }

  // Zuhoerer registrieren:
  private void registriereZuhoerer(){
    btnStart.addActionListener(new BL());
    btnSchreibenPPM.addActionListener(new BLSchreibPPM());
    btnSchreibenPNG.addActionListener(new BLSchreibPNG());
  }

  // Layout aufbauen:
  private void baueLayout(){
    Container cp =getContentPane();
    cp.setLayout(new BorderLayout());
    // NORTH
    Panel pN=new Panel(new FlowLayout(FlowLayout.RIGHT));
    pN.add(btnStart);
    pN.add(btnSchreibenPPM);
    pN.add(btnSchreibenPNG);
    pN.add(lblSchreibName);
    pN.add(tfSchreibName);
    cp.add(pN, BorderLayout.NORTH);
    // CENTER
    cp.add(pZentral, BorderLayout.CENTER);
  }

  // Konstruktor:
  MakePPM(String title){
    super(title);
    erzeugeKomponenten();
    registriereZuhoerer();
    baueLayout();
    pZentral.img=new BufferedImage(pZentral.breite, pZentral.hoehe, BufferedImage.TYPE_INT_ARGB);
    // zur Sicherheit:
    pZentral.istKnopfGedrueckt=false;
  }

  // Zuhoerer (als innere Klasse)

  public class BL implements ActionListener{
    public void actionPerformed(ActionEvent e){
      machBild();
      pZentral.istKnopfGedrueckt=true;
      pZentral.repaint();
    }
  }

  public class BLSchreibPPM implements ActionListener{
    public void actionPerformed(ActionEvent e){
      if(pZentral.istKnopfGedrueckt){
        speicherePPMBild(tfSchreibName.getText());
      }
    }
  }

  public class BLSchreibPNG implements ActionListener{
    public void actionPerformed(ActionEvent e){
      if(pZentral.istKnopfGedrueckt){
        speicherePNGBild(tfSchreibName.getText());
      }
    }
  }

  private void speicherePPMBild(String outFileName){
    PrintWriter outFile=null;
    int rgbWert;
    int rotWert;
    int gruenWert;
    int blauWert;
    int zaehler=0;
    outFileName=outFileName+".ppm";
    // der PrintWriter selbst erzeugt keine Exceptions -- nur event.
    //  seine Erzeugung (mit FileWriter)
    try{
      outFile=new PrintWriter(new FileWriter(outFileName), true);
    } catch (IOException ioe){
      System.err.println("Error beim Schreiben von: "+outFileName+": "+ioe.toString());
      System.exit(2);
    }
    outFile.println("P3");
    outFile.println("# erzeugt durch JAVA-Programm");
    outFile.println(pZentral.breite+" "+pZentral.hoehe);
    outFile.println("255");
    for (int y=0; y<pZentral.hoehe; y++){
      outFile.println("# "+(y+1)+". Zeile");
      for (int x=0; x<pZentral.breite; x++){
        rgbWert=pZentral.img.getRGB(x, y);
        rotWert=((255<<16) & rgbWert)>>>16;
        gruenWert=((255<<8) & rgbWert)>>>8;
        blauWert=(255) & rgbWert;
        outFile.print(rotWert+" "+gruenWert+" "+blauWert+"   ");
        zaehler++;
        if(zaehler==5){
          zaehler=0;
          outFile.println();
        }
      }
      outFile.println();
    }
    outFile.close();
  }

  private void speicherePNGBild(String outFileName){
    String[] formatNamenLesen= ImageIO.getReaderFormatNames();
    String[] formatNamenSchreiben=ImageIO.getWriterFormatNames();
    System.out.println("dem System (ImageIO) bekannte Grafik-Formate:");
    System.out.println("formatNamenLesen: ");
    for (int i=0;i<formatNamenLesen.length; i++){
      System.out.print(formatNamenLesen[i]+"   ");
    }
    System.out.println();
    System.out.println("formatNamenSchreiben: ");
    for (int i=0;i<formatNamenSchreiben.length;i++){
      System.out.print(formatNamenSchreiben[i]+"   ");
    }
    System.out.println();
    System.out.println("Achtung: JPEG-Format: Farb-Verfaelschungen!");
    System.out.println();

    outFileName=outFileName+".png";
    boolean bImageIOok=false;
    try{
      bImageIOok=ImageIO.write(pZentral.img, "PNG", new File(outFileName));
    } catch (IOException ioe){
      System.err.println("Error beim Schreiben von: "+outFileName+": "+ioe.toString());
      System.exit(2);
    }
  }

  private void machBild(){
    int rotWert;
    int gruenWert=0;
    int blauWert;
    int rgbWert;
    for (int y =0; y < pZentral.hoehe; y++){
      blauWert =(y * 255) / (pZentral.hoehe - 1);
      for (int x =0; x < pZentral.breite; x++){
        rotWert =(x * 255) / (pZentral.breite - 1);
        rgbWert=(255 << 24) | (rotWert << 16) | (gruenWert << 8) | blauWert;
        pZentral.img.setRGB(x, y, rgbWert);
      }
    }
/*
// direkt ins Bild zeichnen:
    Graphics g=pZentral.img.getGraphics();
    g.setColor(Color.WHITE);
    g.drawLine(0, pZentral.hoehe-1, pZentral.breite, 0);
 */
  }

  // die eigentliche Arbeit:
  private void doIt(){
    // hier: arbeitslos
  }

  public static void main(String[] args){
    MakePPM meinFrame=new MakePPM("PPMBildSchreiben");
    meinFrame.setDefaultCloseOperation(EXIT_ON_CLOSE);
    meinFrame.setSize(700, 400);
    //		meinFrame.pack();

    meinFrame.setVisible(true);
  }

  class MeinPanel extends JPanel{
    // Exemplar-Variablen:
    boolean istKnopfGedrueckt=false;
    BufferedImage img=null;
    int breite=256;
    int hoehe=256;

    public  void paintComponent(Graphics g){
      super.paintComponent(g);
      if(istKnopfGedrueckt){
        g.drawImage(img, 30, 100, this);
      }
    }
  }
}